package core.controller;

import java.util.ArrayList;

import core.boundary.InputReader;
import core.boundary.UserInterfaceTUI;
import core.controller.cmds.*;
import core.dal.AdminFunctionality;
import core.dal.OperatorFunctionality;
import core.dal.WeightFunctionality;
import core.dto.AdminDTO;
import core.dto.IOperatorDTO;
import core.dto.OperatorDTO;
import exceptions.UserNotFoundException;

public class CommandController {

	private IOperatorDTO currentUser;
	private ArrayList<ICmd> cmdList;
	private ArrayList<ICmd> cmdListAvailable;
	private String currentLevel;
	private UserInterfaceTUI tui;

	public CommandController() {
		cmdListAvailable = new ArrayList<ICmd>();
		cmdList = new ArrayList<ICmd>();
		currentLevel = "Login";
		tui = new UserInterfaceTUI();
	}

	public void start() {
		while (true) {
			createListOfCommandsAvailable();
			tui.showMenu(cmdListAvailable);
			executeCommand(tui.getInput());
		}
	}

	public void executeCommand(String cmd) {
		cmdListAvailable.get(cmdListAvailable.size() - 1).execute(cmd);
	}

	public ArrayList<ICmd> createListOfCommandsAvailable() {
		// Initializes the command list available
		if (currentLevel == "Login") {
			// Resets the list and creates a new list depending on the
			// currentLevel.
			cmdListAvailable.clear();
			// Checks through the cmdList and puts the available commands
			for (int i = cmdList.size(); i > 0; i--) {
				if (cmdList.get(i - 1).getLevel().equals("Login")) {
					cmdListAvailable.add(cmdList.get(i - 1));
				}
			}
			configureCommands();
		}

		if (currentLevel == "Operator") {
			cmdListAvailable.clear();
			// Checks through the cmdList and puts the available commands
			for (int i = cmdList.size(); i > 0; i--) {
				if (cmdList.get(i - 1).getLevel().equals("Operator")) {
					cmdListAvailable.add(cmdList.get(i - 1));

				}
			}
			configureCommands();
		}

		if (currentLevel == "Admin") {
			cmdListAvailable.clear();
			// Checks through the cmdList and puts the available commands
			for (int i = cmdList.size(); i > 0; i--) {
				if (cmdList.get(i - 1).getLevel().equals("Operator")
						|| cmdList.get(i - 1).getLevel().equals("Admin")) {
					cmdListAvailable.add(cmdList.get(i - 1));

				}
			}
			configureCommands();
		}

		if (currentLevel == "WeightApplication") {
			cmdListAvailable.clear();
			// Checks through the cmdList and puts the available commands
			for (int i = cmdList.size(); i > 0; i--) {
				if (cmdList.get(i - 1).getLevel().equals("WeightApplication")
						|| cmdList.get(i - 1).getLevel().equals("Back")) {
					cmdListAvailable.add(cmdList.get(i - 1));

				}
			}
			configureCommands();
		}
		
		return cmdListAvailable;
	}

	public ArrayList<ICmd> getListOfCommandsAvailable() {
		return cmdListAvailable;
	}

	public void addCmd(ICmd cmd) {
		this.cmdList.add(cmd);
	}

	public UserInterfaceTUI getTUI() {
		return this.tui;
	}

	public void setCurrentLevel(String level) {
		currentLevel = level;
	}

	public void setCurrentUser(IOperatorDTO user) {
		this.currentUser = user;
	}

	public IOperatorDTO getCurrentUser() {
		return currentUser;
	}

	// Sets the chains in commands
	private void configureCommands() {
		/*
		 * First added chain is the last being executed which means that it
		 * won't need any nextChains. The last executed command will have a null
		 * nextCommand.
		 */

		if (cmdListAvailable.size() == 1) {
			cmdListAvailable.get(0).setNextCmd(null);
		} else {
			// Sets the next chain towards to the end of the chain
			for (int i = cmdListAvailable.size(); i > 1; i--) {
				cmdListAvailable.get(i - 1).setNextCmd(
						cmdListAvailable.get(i - 2));
			}
		}
	}
}
